package com.px.baolaiapi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.px.common.api.CommonPage;
import com.px.common.constant.Constant;
import com.px.mbg.mapper.InspectionResultMapper;
import com.px.mbg.model.*;
import com.px.baolaiapi.page.KhPage;
import com.px.baolaiapi.service.*;
import com.px.baolaiapi.util.PoiUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 考核Api-结果 服务实现类
 * </p>
 *
 * @author 品讯科技
 * @since 2022-03-21
 */
@Service
public class InspectionResultServiceImpl extends ServiceImpl<InspectionResultMapper, InspectionResult> implements IInspectionResultService {

    static final ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");

    @Autowired
    private IInspectionTemService inspectionTemService;
    @Autowired
    private IInspectionTemItemService inspectionTemItemService;
    @Autowired
    private IInspectionIntoService inspectionIntoService;
    @Autowired
    private ISequenceNumberService sequenceNumberService;
    @Autowired
    private IInspectionUserService inspectionUserService;
    @Autowired
    private IInspectionSxjgService inspectionSxjgService;
    @Autowired
    private IInspectionIsxjgService inspectionIsxjgService;

    @Autowired
    private IUsersService usersService;

    @Override
    public int upload(MultipartFile file) {

        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();

            Workbook workbook = WorkbookFactory.create(inputStream);
            //获取全部的sheet页数
            int numberOfSheets = workbook.getNumberOfSheets();
            if (numberOfSheets > 0) {
                //用于存放模板信息
                Map<String, InspectionResult> temMap = new HashMap<>();
                //用于存放该模板所关联的用户信息
                Map<String, List<InspectionUser>> userMap = new HashMap<>();
                //用于存放该用户需要考核的具体事项
                Map<String, List<InspectionSxjg>> sxMap = new HashMap<>();
                //用于存放事项中的具体指标
                Map<String, List<InspectionIsxjg>> normMap = new HashMap<>();

                String khMonthScope = null;
                for (int i = 0; i < numberOfSheets; i++) {
                    Sheet sheet = workbook.getSheetAt(i);
                    //获取当前sheet有有多少行数据
                    int numberOfRows = sheet.getPhysicalNumberOfRows();
                    if (numberOfRows > 0) {
                        //获取考核模板编码
                        String khTemCode = PoiUtil.getCellValue(sheet.getRow(0).getCell(1));

                        //获取考核模板-事项编码
                        String khTemSxCode = PoiUtil.getCellValue(sheet.getRow(2).getCell(1));

                        //获取考核月份
                        String khMonth = PoiUtil.getCellValue(sheet.getRow(4).getCell(1));

                        if (!temMap.containsKey(khMonth)) {
                            //封装inspectionResult数据
                            InspectionTem inspectionTem = inspectionTemService.getOne(new QueryWrapper<InspectionTem>().lambda().eq(InspectionTem::getCode, khTemCode));
                            InspectionResult inspectionResult = new InspectionResult();
                            inspectionResult.setCode(inspectionTem.getCode());
                            inspectionResult.setName(inspectionTem.getName());
                            inspectionResult.setMonth(khMonth);
                            temMap.put(khMonth, inspectionResult);
                            khMonthScope = khMonth;

                            List<InspectionTemItem> inspectionTemItems = inspectionTemItemService.list(new QueryWrapper<InspectionTemItem>().lambda().eq(InspectionTemItem::getInspectionTemId, inspectionTem.getId()).eq(InspectionTemItem::getIsDelFlag, Constant.IS_ENABLED.ENABLE).orderByAsc(InspectionTemItem::getCreatedTime));

                            //封装InspectionUser数据
                            String inspectionPeople = inspectionTem.getInspectionPeople();
                            if (StringUtils.isNotEmpty(inspectionPeople)) {
                                String[] strings = inspectionPeople.split(",");
                                List<InspectionUser> inspectionUserList = new ArrayList<>();
                                for (String userIdStr : strings) {
                                    InspectionUser inspectionUser = new InspectionUser();
                                    inspectionUser.setUesrId(Long.parseLong(userIdStr));
                                    inspectionUserList.add(inspectionUser);

                                    //封装人员需要考核的事项
                                    if (CollectionUtil.isNotEmpty(inspectionTemItems)) {
                                        List<InspectionSxjg> inspectionSxjgList = new ArrayList<>();
                                        for (InspectionTemItem inspectionTemItem : inspectionTemItems) {

                                            InspectionInto inspectionInto = inspectionIntoService.getById(inspectionTemItem.getInspectionIntoId());

                                            InspectionSxjg inspectionSxjg = new InspectionSxjg();
                                            inspectionSxjg.setInspectionIntoId(inspectionTemItem.getInspectionIntoId());
                                            inspectionSxjg.setInspectionIntoCode(inspectionInto.getCode());
                                            inspectionSxjg.setInspectionIntoName(inspectionInto.getName());
                                            inspectionSxjg.setWeight(inspectionTemItem.getWeight());
                                            inspectionSxjg.setTotalPoints(inspectionTemItem.getTotalPoints());
                                            inspectionSxjg.setAssessment(inspectionTemItem.getAssessment());
                                            inspectionSxjg.setIsCalculate(inspectionInto.getIsCalculate());
                                            inspectionSxjg.setValueField(inspectionInto.getValueField());
                                            inspectionSxjg.setNlms(inspectionInto.getNlms());
                                            inspectionSxjgList.add(inspectionSxjg);
                                        }
                                        sxMap.put(userIdStr, inspectionSxjgList);
                                    } else {
                                        break;
                                    }
                                }
                                userMap.put(inspectionTem.getCode(), inspectionUserList);
                            } else {
                                break;
                            }
                        }

                        //获取有多少列具体的指标
                        Row sheetRow1 = sheet.getRow(5);
                        int cells = sheetRow1.getPhysicalNumberOfCells();
                        String title[] = new String[cells];
                        for (int n = 0; n < cells; n++) {
                            title[n] = sheetRow1.getCell(n).getStringCellValue();
                        }

                        for (int j = 6; j < numberOfRows; j++) {
                            Row sheetRow = sheet.getRow(j);
//                            Cell userCell = sheetRow.getCell(0);
                            String userCellValue = PoiUtil.getCellValue(sheetRow.getCell(0));

                            String key = userCellValue + "-" + khTemSxCode;
                            List<InspectionIsxjg> inspectionIsxjgList;
                            if (normMap.containsKey(key)) {
                                inspectionIsxjgList = normMap.get(key);
                            } else {
                                inspectionIsxjgList = new ArrayList<>();
                            }
                            for (int k = 1; k < cells; k++) {
                                String stringCellValue = "0";
                                Cell rowCell = sheetRow.getCell(k);
                                if (ObjectUtil.isNotEmpty(rowCell)) {
//                                    stringCellValue = rowCell.getStringCellValue();
                                    stringCellValue = PoiUtil.getCellValue(rowCell);
                                }
                                String zhibiao = title[k];
                                InspectionIsxjg inspectionIsxjg = new InspectionIsxjg();
                                inspectionIsxjg.setName(zhibiao);
                                inspectionIsxjg.setRecordValue(stringCellValue);
                                inspectionIsxjgList.add(inspectionIsxjg);
                            }
                            normMap.put(key, inspectionIsxjgList);
                        }


                    }
                }

                boolean isSuccess = false;
                long oId = 0;
                if (!temMap.isEmpty()) {
                    InspectionResult inspectionResult = temMap.get(khMonthScope);
                    inspectionResult.setIversion(sequenceNumberService.createSequenceNumberNop("khMonth", "yyyyMM", 2));
                    if (isSuccess = this.save(inspectionResult)) {
                        oId = inspectionResult.getId();
                        List<InspectionUser> inspectionUserList = userMap.get(inspectionResult.getCode());
                        if (CollectionUtil.isNotEmpty(inspectionUserList)) {
                            for (InspectionUser inspectionUser : inspectionUserList) {
                                inspectionUser.setIrId(inspectionResult.getId());

                                //封装user
                                Users users = usersService.getById(inspectionUser.getUesrId());
                                if (ObjectUtil.isNotEmpty(users)) {

                                    if (isSuccess = inspectionUserService.save(inspectionUser)) {
                                        List<InspectionSxjg> inspectionSxjgList = sxMap.get(inspectionUser.getUesrId().toString());
                                        if (CollectionUtil.isNotEmpty(inspectionSxjgList)) {
                                            for (InspectionSxjg inspectionSxjg : inspectionSxjgList) {
                                                inspectionSxjg.setIuId(inspectionUser.getId());
                                                if (isSuccess = inspectionSxjgService.save(inspectionSxjg)) {
                                                    String userKey = users.getAccount() + "<" + users.getUsername() + ">" + "-" + inspectionSxjg.getInspectionIntoCode();
                                                    List<InspectionIsxjg> inspectionIsxjgList = normMap.get(userKey);
                                                    if (CollectionUtil.isNotEmpty(inspectionIsxjgList)) {
                                                        inspectionIsxjgList.forEach(inspectionIsxjg -> inspectionIsxjg.setIsxId(inspectionSxjg.getId()));
                                                        isSuccess = inspectionIsxjgService.saveBatch(inspectionIsxjgList);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if (isSuccess) {
                    //开始计算
                    isSuccess = operationData(oId);
                }
                return isSuccess ? 1 : 0;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public boolean operationData(long oId) {
        boolean isSuccess = false;
        if (oId > 0) {
            InspectionResult inspectionResult = this.getById(oId);
            BigDecimal avgScore =new BigDecimal(0);
            int userNum = 0;

            //查询用户
            List<InspectionUser> inspectionUsers = inspectionUserService.list(new QueryWrapper<InspectionUser>().lambda().eq(InspectionUser::getIrId, oId));
            if (CollectionUtil.isNotEmpty(inspectionUsers)) {
                for (InspectionUser inspectionUser : inspectionUsers) {
                    userNum++;
                    BigDecimal userScore =new BigDecimal(0);

                    List<InspectionSxjg> inspectionSxjgList = inspectionSxjgService.list(new QueryWrapper<InspectionSxjg>().lambda().eq(InspectionSxjg::getIuId, inspectionUser.getId()));
                    if (CollectionUtil.isNotEmpty(inspectionSxjgList)) {
                        for (InspectionSxjg inspectionSxjg : inspectionSxjgList) {
                            if (inspectionSxjg.getIsCalculate() == 0) {
                                //直接取分数
                                String valueField = inspectionSxjg.getValueField();
                                List<InspectionIsxjg> inspectionIsxjgs = inspectionIsxjgService.list(new QueryWrapper<InspectionIsxjg>().lambda().eq(InspectionIsxjg::getIsxId, inspectionSxjg.getId()).eq(InspectionIsxjg::getName, valueField));
                                if (CollectionUtil.isNotEmpty(inspectionIsxjgs)) {
                                    String recordValue = inspectionIsxjgs.get(0).getRecordValue();
                                    inspectionSxjg.setScore(recordValue);
                                    BigDecimal mul = NumberUtil.mul(recordValue, inspectionSxjg.getWeight());
                                    inspectionSxjg.setPerformance(mul.toString());
                                    userScore=userScore.add(mul);

                                } else {
                                    inspectionSxjg.setScore(0 + "");
                                    inspectionSxjg.setPerformance(0 + "");
                                }
                            } else {
                                //通过公式计算分数
                                String nlms = inspectionSxjg.getNlms();
                                List<InspectionIsxjg> inspectionIsxjgs = inspectionIsxjgService.list(new QueryWrapper<InspectionIsxjg>().lambda().eq(InspectionIsxjg::getIsxId, inspectionSxjg.getId()));
                                if (CollectionUtil.isNotEmpty(inspectionIsxjgs)) {
                                    for (InspectionIsxjg inspectionIsxjg : inspectionIsxjgs) {
                                        nlms = nlms.replaceAll(inspectionIsxjg.getName(), inspectionIsxjg.getRecordValue());
                                    }
                                    try {
                                        String recordValue = NumberUtil.roundStr(String.valueOf(jse.eval(nlms)), 4);
                                        inspectionSxjg.setScore(recordValue);
                                        BigDecimal mul = NumberUtil.mul(recordValue, inspectionSxjg.getWeight());
                                        inspectionSxjg.setPerformance(mul.toString());
                                        userScore=userScore.add(mul);
                                    } catch (ScriptException e) {
                                        e.printStackTrace();
                                    }

                                } else {
                                    inspectionSxjg.setScore(0 + "");
                                    inspectionSxjg.setPerformance(0 + "");
                                }
                            }
                            isSuccess = inspectionSxjgService.updateById(inspectionSxjg);
                        }
                    }
                    avgScore= avgScore.add(userScore);
                    inspectionUser.setScore(userScore + "");
                    isSuccess = inspectionUserService.updateById(inspectionUser);
                }
            }

            inspectionResult.setAvg(NumberUtil.div(avgScore.toString(), userNum + "", 4).toString());
            isSuccess = this.updateById(inspectionResult);

        }
        return isSuccess;
    }

    @Override
    public CommonPage queryPage(KhPage khPage) {
        LambdaQueryWrapper<InspectionResult> queryWrapper = Wrappers.lambdaQuery(InspectionResult.class);
        queryWrapper.orderByDesc(InspectionResult::getCreatedTime);
        String code = khPage.getCode();
        if (StringUtils.isNotEmpty(code)) {
            queryWrapper.like(InspectionResult::getCode, code);
        }
        String name = khPage.getName();
        if (StringUtils.isNotEmpty(name)) {
            queryWrapper.like(InspectionResult::getName, name);
        }
        String month = khPage.getMonth();
        if (StringUtils.isNotEmpty(month)) {
            queryWrapper.like(InspectionResult::getMonth, month);
        }
        CommonPage commonPage = CommonPage.restPage(this.page(new Page<>(khPage.getPageNum(), khPage.getPageRow()), queryWrapper));
        List<InspectionResult> inspectionResults = commonPage.getList();
        if (CollectionUtil.isNotEmpty(inspectionResults)) {
            List<JSONObject> jsonObjects = new ArrayList<>();
            for (InspectionResult inspectionResult : inspectionResults) {

                inspectionResult.setAvg(new BigDecimal(inspectionResult.getAvg()).stripTrailingZeros().toPlainString());

                JSONObject jsonObject = JSONUtil.parseObj(inspectionResult);
                jsonObject.set("userList", queryUserScoreById(inspectionResult.getId()));
                jsonObjects.add(jsonObject);
            }
            commonPage.setList(jsonObjects);
        }
        return commonPage;
    }

    /**
     * 通过irId查询用户得分
     *
     * @param irId 红外id
     * @return {@link List< JSONObject >}
     */
    @Override
    public List<JSONObject> queryUserScoreById(long irId) {
        List<JSONObject> jsonObjects = new ArrayList<>();
        List<InspectionUser> inspectionUsers = inspectionUserService.list(new QueryWrapper<InspectionUser>().lambda().eq(InspectionUser::getIrId, irId));
        if (CollectionUtil.isNotEmpty(inspectionUsers)) {
            for (InspectionUser inspectionUser : inspectionUsers) {
                inspectionUser.setScore(new BigDecimal(inspectionUser.getScore()).stripTrailingZeros().toPlainString());
                JSONObject jsonObject = JSONUtil.parseObj(inspectionUser);
                Users users = usersService.getById(inspectionUser.getUesrId());
                if (ObjectUtil.isNotEmpty(users)) {
                    jsonObject.set("userName", users.getUsername());
                }
                jsonObjects.add(jsonObject);
            }
        }
        return jsonObjects;
    }

    /**
     * 通过iUserId查询用户详细得分
     *
     * @param iUserId 我的用户id
     * @return {@link List<InspectionSxjg>}
     */
    @Override
    public List<InspectionSxjg> queryUserItemScoreByIuserId(long iUserId) {
        List<InspectionSxjg> list = inspectionSxjgService.list(new QueryWrapper<InspectionSxjg>().lambda().eq(InspectionSxjg::getIuId, iUserId));
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(inspectionSxjg -> {
                inspectionSxjg.setScore(new BigDecimal(inspectionSxjg.getScore()).stripTrailingZeros().toPlainString());
                inspectionSxjg.setPerformance(new BigDecimal(inspectionSxjg.getPerformance()).stripTrailingZeros().toPlainString());
            });
        }
        return list;
    }
}
